home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume17 / pax / part04 < prev    next >
Encoding:
Internet Message Format  |  1989-02-02  |  46.8 KB

  1. Subject:  v17i077:  Usenix/IEEE POSIX replacement for TAR and CPIO, Part04/06
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Mark H. Colburn <mark@jhereg.jhereg.mn.org>
  6. Posting-number: Volume 17, Issue 77
  7. Archive-name: pax/part04
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 4 (of 6)."
  16. # Contents:  extract.c list.c pax.1
  17. # Wrapped by mark@jhereg on Tue Dec 27 19:37:53 1988
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f extract.c -a "${1}" != "-c" ; then 
  20.   echo shar: Will not over-write existing file \"extract.c\"
  21. else
  22. echo shar: Extracting \"extract.c\" \(14327 characters\)
  23. sed "s/^X//" >extract.c <<'END_OF_extract.c'
  24. X/* $Source: /u/mark/src/pax/RCS/extract.c,v $
  25. X *
  26. X * $Revision: 1.1 $
  27. X *
  28. X * extract.c - Extract files from a tar archive. 
  29. X *
  30. X * DESCRIPTION
  31. X *
  32. X * AUTHOR
  33. X *
  34. X *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  35. X *
  36. X * Sponsored by The USENIX Association for public distribution. 
  37. X *
  38. X * Copyright (c) 1989 Mark H. Colburn.
  39. X * All rights reserved.
  40. X *
  41. X * Redistribution and use in source and binary forms are permitted
  42. X * provided that the above copyright notice is duplicated in all such 
  43. X * forms and that any documentation, advertising materials, and other 
  44. X * materials related to such distribution and use acknowledge that the 
  45. X * software was developed * by Mark H. Colburn and sponsored by The 
  46. X * USENIX Association. 
  47. X *
  48. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  49. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  50. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  51. X *
  52. X * $Log:    extract.c,v $
  53. X * Revision 1.1  88/12/23  18:02:07  mark
  54. X * Initial revision
  55. X * 
  56. X */
  57. X
  58. X#ifndef lint
  59. Xstatic char *ident = "$Id: extract.c,v 1.1 88/12/23 18:02:07 mark Rel $";
  60. Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  61. X#endif /* ! lint */
  62. X
  63. X
  64. X/* Headers */
  65. X
  66. X#include "pax.h"
  67. X
  68. X
  69. X/* Defines */
  70. X
  71. X/*
  72. X * Swap bytes. 
  73. X */
  74. X#define    SWAB(n)    ((((ushort)(n) >> 8) & 0xff) | (((ushort)(n) << 8) & 0xff00))
  75. X
  76. X
  77. X/* Function Prototypes */
  78. X
  79. X#ifdef __STDC__
  80. X
  81. Xstatic int inbinary(char *, char *, Stat *);
  82. Xstatic int inascii(char *, char *, Stat *);
  83. Xstatic int inswab(char *, char *, Stat *);
  84. Xstatic int readtar(char *, Stat *);
  85. Xstatic int readcpio(char *, Stat *);
  86. X
  87. X#else /* !__STDC__ */
  88. X
  89. Xstatic int inbinary();
  90. Xstatic int inascii();
  91. Xstatic int inswab();
  92. Xstatic int readtar();
  93. Xstatic int readcpio();
  94. X
  95. X#endif /* __STDC__ */
  96. X
  97. X
  98. X/* read_archive - read in an archive
  99. X *
  100. X * DESCRIPTION
  101. X *
  102. X *    Read_archive is the central entry point for reading archives.
  103. X *    Read_archive determines the proper archive functions to call
  104. X *    based upon the archive type being processed.
  105. X *
  106. X * RETURNS
  107. X *
  108. X */
  109. X
  110. X#ifdef __STDC__
  111. X
  112. Xint read_archive(void)
  113. X
  114. X#else
  115. X    
  116. Xint read_archive()
  117. X
  118. X#endif
  119. X{
  120. X    Stat            sb;
  121. X    char            name[PATH_MAX + 1];
  122. X    int             match;
  123. X    int            pad;
  124. X
  125. X    name_gather();        /* get names from command line */
  126. X    name[0] = '\0';
  127. X    while (get_header(name, &sb) == 0) {
  128. X    match = name_match(name) ^ f_reverse_match;
  129. X    if (f_list) {        /* only wanted a table of contents */
  130. X        if (match) {
  131. X        print_entry(name, &sb);
  132. X        }
  133. X        if (((ar_format == TAR) 
  134. X        ? buf_skip(ROUNDUP((OFFSET) sb.sb_size, BLOCKSIZE)) 
  135. X        : buf_skip((OFFSET) sb.sb_size)) < 0) {
  136. X        warn(name, "File data is corrupt");
  137. X        }
  138. X    } else if (match) {
  139. X        if (rplhead != NULL) {
  140. X        rpl_name(name);
  141. X        if (strlen(name) == 0) {
  142. X            continue;
  143. X        }
  144. X        }
  145. X        if (get_disposition("extract", name) || 
  146. X                get_newname(name, sizeof(name))) {
  147. X        /* skip file... */
  148. X        if (((ar_format == TAR) 
  149. X            ? buf_skip(ROUNDUP((OFFSET) sb.sb_size, BLOCKSIZE)) 
  150. X            : buf_skip((OFFSET) sb.sb_size)) < 0) {
  151. X            warn(name, "File data is corrupt");
  152. X        }
  153. X        continue;
  154. X        } 
  155. X        if (inentry(name, &sb) < 0) {
  156. X        warn(name, "File data is corrupt");
  157. X        }
  158. X        if (f_verbose) {
  159. X        print_entry(name, &sb);
  160. X        }
  161. X        if (ar_format == TAR && sb.sb_nlink > 1) {
  162. X        /*
  163. X         * This kludge makes sure that the link table is cleared
  164. X         * before attempting to process any other links.
  165. X         */
  166. X        if (sb.sb_nlink > 1) {
  167. X            linkfrom(name, &sb);
  168. X        }
  169. X        }
  170. X        if (ar_format == TAR && (pad = sb.sb_size % BLOCKSIZE) != 0) {
  171. X        pad = BLOCKSIZE - pad;
  172. X        buf_skip((OFFSET) pad);
  173. X        }
  174. X    } else {
  175. X        if (((ar_format == TAR) 
  176. X        ? buf_skip(ROUNDUP((OFFSET) sb.sb_size, BLOCKSIZE)) 
  177. X        : buf_skip((OFFSET) sb.sb_size)) < 0) {
  178. X        warn(name, "File data is corrupt");
  179. X        }
  180. X    }
  181. X    }
  182. X
  183. X    close_archive();
  184. X}
  185. X
  186. X
  187. X
  188. X/* get_header - figures which type of header needs to be read.
  189. X *
  190. X * DESCRIPTION
  191. X *
  192. X *    This is merely a single entry point for the two types of archive
  193. X *    headers which are supported.  The correct header is selected
  194. X *    depending on the archive type.
  195. X *
  196. X * PARAMETERS
  197. X *
  198. X *    char    *name    - name of the file (passed to header routine)
  199. X *    Stat    *asb    - Stat block for the file (passed to header routine)
  200. X *
  201. X * RETURNS
  202. X *
  203. X *    Returns the value which was returned by the proper header
  204. X *    function.
  205. X */
  206. X
  207. X#ifdef __STDC__
  208. X
  209. Xint get_header(char *name, Stat *asb)
  210. X
  211. X#else
  212. X    
  213. Xint get_header(name, asb)
  214. Xchar *name;
  215. XStat *asb;
  216. X
  217. X#endif
  218. X{
  219. X    if (ar_format == TAR) {
  220. X    return(readtar(name, asb));
  221. X    } else {
  222. X    return(readcpio(name, asb));
  223. X    }
  224. X}
  225. X
  226. X
  227. X/* readtar - read a tar header
  228. X *
  229. X * DESCRIPTION
  230. X *
  231. X *    Tar_head read a tar format header from the archive.  The name
  232. X *    and asb parameters are modified as appropriate for the file listed
  233. X *    in the header.   Name is assumed to be a pointer to an array of
  234. X *    at least PATH_MAX bytes.
  235. X *
  236. X * PARAMETERS
  237. X *
  238. X *    char    *name     - name of the file for which the header is
  239. X *              for.  This is modified and passed back to
  240. X *              the caller.
  241. X *    Stat    *asb    - Stat block for the file for which the header
  242. X *              is for.  The fields of the stat structure are
  243. X *              extracted from the archive header.  This is
  244. X *              also passed back to the caller.
  245. X *
  246. X * RETURNS
  247. X *
  248. X *    Returns 0 if a valid header was found, or -1 if EOF is
  249. X *    encountered.
  250. X */
  251. X
  252. X#ifdef __STDC__
  253. X
  254. Xstatic int readtar(char *name, Stat *asb)
  255. X
  256. X#else
  257. X    
  258. Xstatic int readtar(name, asb)
  259. Xchar    *name;
  260. XStat    *asb;
  261. X
  262. X#endif
  263. X{
  264. X    int             status = 3;    /* Initial status at start of archive */
  265. X    static int      prev_status;
  266. X
  267. X    for (;;) {
  268. X    prev_status = status;
  269. X    status = read_header(name, asb);
  270. X    switch (status) {
  271. X    case 1:        /* Valid header */
  272. X        return(0);
  273. X    case 0:        /* Invalid header */
  274. X        switch (prev_status) {
  275. X        case 3:        /* Error on first record */
  276. X        warn(ar_file, "This doesn't look like a tar archive");
  277. X        /* FALLTHRU */
  278. X        case 2:        /* Error after record of zeroes */
  279. X        case 1:        /* Error after header rec */
  280. X        warn(ar_file, "Skipping to next file...");
  281. X        /* FALLTHRU */
  282. X        default:
  283. X        case 0:        /* Error after error */
  284. X        break;
  285. X        }
  286. X        break;
  287. X
  288. X    case 2:            /* Record of zeroes */
  289. X    case EOF:        /* End of archive */
  290. X    default:
  291. X        return(-1);
  292. X    }
  293. X    }
  294. X}
  295. X
  296. X
  297. X/* readcpio - read a CPIO header 
  298. X *
  299. X * DESCRIPTION
  300. X *
  301. X *    Read in a cpio header.  Understands how to determine and read ASCII, 
  302. X *    binary and byte-swapped binary headers.  Quietly translates 
  303. X *    old-fashioned binary cpio headers (and arranges to skip the possible 
  304. X *    alignment byte). Returns zero if successful, -1 upon archive trailer. 
  305. X *
  306. X * PARAMETERS
  307. X *
  308. X *    char    *name     - name of the file for which the header is
  309. X *              for.  This is modified and passed back to
  310. X *              the caller.
  311. X *    Stat    *asb    - Stat block for the file for which the header
  312. X *              is for.  The fields of the stat structure are
  313. X *              extracted from the archive header.  This is
  314. X *              also passed back to the caller.
  315. X *
  316. X * RETURNS
  317. X *
  318. X *    Returns 0 if a valid header was found, or -1 if EOF is
  319. X *    encountered.
  320. X */
  321. X
  322. X#ifdef __STDC__
  323. X
  324. Xstatic int readcpio(char *name, Stat *asb)
  325. X
  326. X#else
  327. X    
  328. Xstatic int readcpio(name, asb)
  329. Xchar           *name;
  330. XStat           *asb;
  331. X
  332. X#endif
  333. X{
  334. X    OFFSET          skipped;
  335. X    char            magic[M_STRLEN];
  336. X    static int      align;
  337. X
  338. X    if (align > 0) {
  339. X    buf_skip((OFFSET) align);
  340. X    }
  341. X    align = 0;
  342. X    for (;;) {
  343. X    buf_read(magic, M_STRLEN);
  344. X    skipped = 0;
  345. X    while ((align = inascii(magic, name, asb)) < 0
  346. X           && (align = inbinary(magic, name, asb)) < 0
  347. X           && (align = inswab(magic, name, asb)) < 0) {
  348. X        if (++skipped == 1) {
  349. X        if (total - sizeof(magic) == 0) {
  350. X            fatal("Unrecognizable archive");
  351. X        }
  352. X        warnarch("Bad magic number", (OFFSET) sizeof(magic));
  353. X        if (name[0]) {
  354. X            warn(name, "May be corrupt");
  355. X        }
  356. X        }
  357. X        memcpy(magic, magic + 1, sizeof(magic) - 1);
  358. X        buf_read(magic + sizeof(magic) - 1, 1);
  359. X    }
  360. X    if (skipped) {
  361. X        warnarch("Apparently resynchronized", (OFFSET) sizeof(magic));
  362. X        warn(name, "Continuing");
  363. X    }
  364. X    if (strcmp(name, TRAILER) == 0) {
  365. X        return (-1);
  366. X    }
  367. X    if (nameopt(name) >= 0) {
  368. X        break;
  369. X    }
  370. X    buf_skip((OFFSET) asb->sb_size + align);
  371. X    }
  372. X#ifdef    S_IFLNK
  373. X    if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  374. X    if (buf_read(asb->sb_link, (uint) asb->sb_size) < 0) {
  375. X        warn(name, "Corrupt symbolic link");
  376. X        return (readcpio(name, asb));
  377. X    }
  378. X    asb->sb_link[asb->sb_size] = '\0';
  379. X    asb->sb_size = 0;
  380. X    }
  381. X#endif                /* S_IFLNK */
  382. X
  383. X    /* destroy absolute pathnames for security reasons */
  384. X    if (name[0] == '/') {
  385. X    if (name[1]) {
  386. X        while (name[0] = name[1]) {
  387. X        ++name;
  388. X        }
  389. X    } else {
  390. X        name[0] = '.';
  391. X    }
  392. X    }
  393. X    asb->sb_atime = asb->sb_ctime = asb->sb_mtime;
  394. X    if (asb->sb_nlink > 1) {
  395. X    linkto(name, asb);
  396. X    }
  397. X    return (0);
  398. X}
  399. X
  400. X
  401. X/* inswab - read a reversed by order binary header
  402. X *
  403. X * DESCRIPTIONS
  404. X *
  405. X *    Reads a byte-swapped CPIO binary archive header
  406. X *
  407. X * PARMAMETERS
  408. X *
  409. X *    char    *magic    - magic number to match
  410. X *    char    *name    - name of the file which is stored in the header.
  411. X *              (modified and passed back to caller).
  412. X *    Stat    *asb    - stat block for the file (modified and passed back
  413. X *              to the caller).
  414. X *
  415. X *
  416. X * RETURNS
  417. X *
  418. X *     Returns the number of trailing alignment bytes to skip; -1 if 
  419. X *    unsuccessful. 
  420. X *
  421. X */
  422. X
  423. X#ifdef __STDC__
  424. X
  425. Xstatic int inswab(char *magic, char *name, Stat *asb)
  426. X
  427. X#else
  428. X    
  429. Xstatic int inswab(magic, name, asb)
  430. Xchar           *magic;
  431. Xchar           *name;
  432. XStat           *asb;
  433. X
  434. X#endif
  435. X{
  436. X    ushort          namesize;
  437. X    uint            namefull;
  438. X    Binary          binary;
  439. X
  440. X    if (*((ushort *) magic) != SWAB(M_BINARY)) {
  441. X    return (-1);
  442. X    }
  443. X    memcpy((char *) &binary,
  444. X          magic + sizeof(ushort),
  445. X          M_STRLEN - sizeof(ushort));
  446. X    if (buf_read((char *) &binary + M_STRLEN - sizeof(ushort),
  447. X         sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0) {
  448. X    warnarch("Corrupt swapped header",
  449. X         (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
  450. X    return (-1);
  451. X    }
  452. X    asb->sb_dev = (dev_t) SWAB(binary.b_dev);
  453. X    asb->sb_ino = (ino_t) SWAB(binary.b_ino);
  454. X    asb->sb_mode = SWAB(binary.b_mode);
  455. X    asb->sb_uid = SWAB(binary.b_uid);
  456. X    asb->sb_gid = SWAB(binary.b_gid);
  457. X    asb->sb_nlink = SWAB(binary.b_nlink);
  458. X    asb->sb_rdev = (dev_t) SWAB(binary.b_rdev);
  459. X    asb->sb_mtime = SWAB(binary.b_mtime[0]) << 16 | SWAB(binary.b_mtime[1]);
  460. X    asb->sb_size = SWAB(binary.b_size[0]) << 16 | SWAB(binary.b_size[1]);
  461. X    if ((namesize = SWAB(binary.b_name)) == 0 || namesize >= PATH_MAX) {
  462. X    warnarch("Bad swapped pathname length",
  463. X         (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
  464. X    return (-1);
  465. X    }
  466. X    if (buf_read(name, namefull = namesize + namesize % 2) < 0) {
  467. X    warnarch("Corrupt swapped pathname", (OFFSET) namefull);
  468. X    return (-1);
  469. X    }
  470. X    if (name[namesize - 1] != '\0') {
  471. X    warnarch("Bad swapped pathname", (OFFSET) namefull);
  472. X    return (-1);
  473. X    }
  474. X    return (asb->sb_size % 2);
  475. X}
  476. X
  477. X
  478. X/* inascii - read in an ASCII cpio header
  479. X *
  480. X * DESCRIPTION
  481. X *
  482. X *    Reads an ASCII format cpio header
  483. X *
  484. X * PARAMETERS
  485. X *
  486. X *    char    *magic    - magic number to match
  487. X *    char    *name    - name of the file which is stored in the header.
  488. X *              (modified and passed back to caller).
  489. X *    Stat    *asb    - stat block for the file (modified and passed back
  490. X *              to the caller).
  491. X *
  492. X * RETURNS
  493. X *
  494. X *     Returns zero if successful; -1 otherwise. Assumes that  the entire 
  495. X *    magic number has been read. 
  496. X */
  497. X
  498. X#ifdef __STDC__
  499. X
  500. Xstatic int inascii(char *magic, char *name, Stat *asb)
  501. X
  502. X#else
  503. X    
  504. Xstatic int inascii(magic, name, asb)
  505. Xchar           *magic;
  506. Xchar           *name;
  507. XStat           *asb;
  508. X
  509. X#endif
  510. X{
  511. X    uint            namelen;
  512. X    char            header[H_STRLEN + 1];
  513. X
  514. X    if (strncmp(magic, M_ASCII, M_STRLEN) != 0) {
  515. X    return (-1);
  516. X    }
  517. X    if (buf_read(header, H_STRLEN) < 0) {
  518. X    warnarch("Corrupt ASCII header", (OFFSET) H_STRLEN);
  519. X    return (-1);
  520. X    }
  521. X    header[H_STRLEN] = '\0';
  522. X    if (sscanf(header, H_SCAN, &asb->sb_dev,
  523. X           &asb->sb_ino, &asb->sb_mode, &asb->sb_uid,
  524. X           &asb->sb_gid, &asb->sb_nlink, &asb->sb_rdev,
  525. X           &asb->sb_mtime, &namelen, &asb->sb_size) != H_COUNT) {
  526. X    warnarch("Bad ASCII header", (OFFSET) H_STRLEN);
  527. X    return (-1);
  528. X    }
  529. X    if (namelen == 0 || namelen >= PATH_MAX) {
  530. X    warnarch("Bad ASCII pathname length", (OFFSET) H_STRLEN);
  531. X    return (-1);
  532. X    }
  533. X    if (buf_read(name, namelen) < 0) {
  534. X    warnarch("Corrupt ASCII pathname", (OFFSET) namelen);
  535. X    return (-1);
  536. X    }
  537. X    if (name[namelen - 1] != '\0') {
  538. X    warnarch("Bad ASCII pathname", (OFFSET) namelen);
  539. X    return (-1);
  540. X    }
  541. X    return (0);
  542. X}
  543. X
  544. X
  545. X/* inbinary - read a binary header
  546. X *
  547. X * DESCRIPTION
  548. X *
  549. X *    Reads a CPIO format binary header.
  550. X *
  551. X * PARAMETERS
  552. X *
  553. X *    char    *magic    - magic number to match
  554. X *    char    *name    - name of the file which is stored in the header.
  555. X *              (modified and passed back to caller).
  556. X *    Stat    *asb    - stat block for the file (modified and passed back
  557. X *              to the caller).
  558. X *
  559. X * RETURNS
  560. X *
  561. X *     Returns the number of trailing alignment bytes to skip; -1 if 
  562. X *    unsuccessful. 
  563. X */
  564. X
  565. X#ifdef __STDC__
  566. X
  567. Xstatic int inbinary(char *magic, char *name, Stat *asb)
  568. X
  569. X#else
  570. X    
  571. Xstatic int inbinary(magic, name, asb)
  572. Xchar           *magic;
  573. Xchar           *name;
  574. XStat           *asb;
  575. X
  576. X#endif
  577. X{
  578. X    uint            namefull;
  579. X    Binary          binary;
  580. X
  581. X    if (*((ushort *) magic) != M_BINARY) {
  582. X    return (-1);
  583. X    }
  584. X    memcpy((char *) &binary,
  585. X          magic + sizeof(ushort),
  586. X          M_STRLEN - sizeof(ushort));
  587. X    if (buf_read((char *) &binary + M_STRLEN - sizeof(ushort),
  588. X         sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0) {
  589. X    warnarch("Corrupt binary header",
  590. X         (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
  591. X    return (-1);
  592. X    }
  593. X    asb->sb_dev = binary.b_dev;
  594. X    asb->sb_ino = binary.b_ino;
  595. X    asb->sb_mode = binary.b_mode;
  596. X    asb->sb_uid = binary.b_uid;
  597. X    asb->sb_gid = binary.b_gid;
  598. X    asb->sb_nlink = binary.b_nlink;
  599. X    asb->sb_rdev = binary.b_rdev;
  600. X    asb->sb_mtime = binary.b_mtime[0] << 16 | binary.b_mtime[1];
  601. X    asb->sb_size = binary.b_size[0] << 16 | binary.b_size[1];
  602. X    if (binary.b_name == 0 || binary.b_name >= PATH_MAX) {
  603. X    warnarch("Bad binary pathname length",
  604. X         (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
  605. X    return (-1);
  606. X    }
  607. X    if (buf_read(name, namefull = binary.b_name + binary.b_name % 2) < 0) {
  608. X    warnarch("Corrupt binary pathname", (OFFSET) namefull);
  609. X    return (-1);
  610. X    }
  611. X    if (name[binary.b_name - 1] != '\0') {
  612. X    warnarch("Bad binary pathname", (OFFSET) namefull);
  613. X    return (-1);
  614. X    }
  615. X    return (asb->sb_size % 2);
  616. X}
  617. END_OF_extract.c
  618. if test 14327 -ne `wc -c <extract.c`; then
  619.     echo shar: \"extract.c\" unpacked with wrong size!
  620. fi
  621. # end of overwriting check
  622. fi
  623. if test -f list.c -a "${1}" != "-c" ; then 
  624.   echo shar: Will not over-write existing file \"list.c\"
  625. else
  626. echo shar: Extracting \"list.c\" \(16229 characters\)
  627. sed "s/^X//" >list.c <<'END_OF_list.c'
  628. X/* $Source: /u/mark/src/pax/RCS/list.c,v $
  629. X *
  630. X * $Revision: 1.1 $
  631. X *
  632. X * list.c - List all files on an archive
  633. X *
  634. X * DESCRIPTION
  635. X *
  636. X *    These function are needed to support archive table of contents and
  637. X *    verbose mode during extraction and creation of achives.
  638. X *
  639. X * AUTHOR
  640. X *
  641. X *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  642. X *
  643. X * Sponsored by The USENIX Association for public distribution. 
  644. X *
  645. X * Copyright (c) 1989 Mark H. Colburn.
  646. X * All rights reserved.
  647. X *
  648. X * Redistribution and use in source and binary forms are permitted
  649. X * provided that the above copyright notice is duplicated in all such 
  650. X * forms and that any documentation, advertising materials, and other 
  651. X * materials related to such distribution and use acknowledge that the 
  652. X * software was developed * by Mark H. Colburn and sponsored by The 
  653. X * USENIX Association. 
  654. X *
  655. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  656. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  657. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  658. X *
  659. X * $Log:    list.c,v $
  660. X * Revision 1.1  88/12/23  18:02:14  mark
  661. X * Initial revision
  662. X * 
  663. X */
  664. X
  665. X#ifndef lint
  666. Xstatic char *ident = "$Id: list.c,v 1.1 88/12/23 18:02:14 mark Rel $";
  667. Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  668. X#endif /* ! lint */
  669. X
  670. X
  671. X/* Headers */
  672. X
  673. X#include "pax.h"
  674. X
  675. X
  676. X/* Defines */
  677. X
  678. X/*
  679. X * isodigit returns non zero iff argument is an octal digit, zero otherwise
  680. X */
  681. X#define    ISODIGIT(c)    (((c) >= '0') && ((c) <= '7'))
  682. X
  683. X
  684. X/* Function Prototypes */
  685. X
  686. X#ifdef __STDC__
  687. X
  688. Xstatic void cpio_entry(char *, Stat *);
  689. Xstatic void tar_entry(char *, Stat *);
  690. Xstatic void pax_entry(char *, Stat *);
  691. Xstatic void print_mode(ushort);
  692. Xstatic long from_oct(int digs, char *where);
  693. X
  694. X#else /* !__STDC__ */
  695. X
  696. Xstatic void cpio_entry();
  697. Xstatic void tar_entry();
  698. Xstatic void pax_entry();
  699. Xstatic void print_mode();
  700. Xstatic long from_oct();
  701. X
  702. X#endif /* __STDC__ */
  703. X
  704. X
  705. X/* Internal Identifiers */
  706. X
  707. Xstatic char       *monnames[] = {
  708. X    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  709. X    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  710. X};
  711. X
  712. X
  713. X/* read_header - read a header record
  714. X *
  715. X * DESCRIPTION
  716. X *
  717. X *     Read a record that's supposed to be a header record. Return its 
  718. X *    address in "head", and if it is good, the file's size in 
  719. X *    asb->sb_size.  Decode things from a file header record into a "Stat". 
  720. X *    Also set "head_standard" to !=0 or ==0 depending whether header record 
  721. X *    is "Unix Standard" tar format or regular old tar format. 
  722. X *
  723. X * PARAMETERS
  724. X *
  725. X *    char   *name        - pointer which will contain name of file
  726. X *    Stat   *asb        - pointer which will contain stat info
  727. X *
  728. X * RETURNS
  729. X *
  730. X *     Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a 
  731. X *     record full of zeros (EOF marker). 
  732. X */
  733. X
  734. X#ifdef __STDC__
  735. X
  736. Xint read_header(char *name, Stat *asb)
  737. X
  738. X#else
  739. X    
  740. Xint read_header(name, asb)
  741. Xchar           *name;
  742. XStat           *asb;
  743. X
  744. X#endif
  745. X{
  746. X    int             i;
  747. X    long            sum;
  748. X    long        recsum;
  749. X    Link           *link;
  750. X    char           *p;
  751. X    char            hdrbuf[BLOCKSIZE];
  752. X
  753. X    memset((char *)asb, 0, sizeof(Stat));
  754. X    /* read the header from the buffer */
  755. X    if (buf_read(hdrbuf, BLOCKSIZE) != 0) {
  756. X    return (EOF);
  757. X    }
  758. X
  759. X    strcpy(name, hdrbuf);
  760. X
  761. X    recsum = from_oct(8, &hdrbuf[148]);
  762. X    sum = 0;
  763. X    p = hdrbuf;
  764. X    for (i = 0 ; i < 500; i++) {
  765. X
  766. X    /*
  767. X     * We can't use unsigned char here because of old compilers, e.g. V7. 
  768. X     */
  769. X    sum += 0xFF & *p++;
  770. X    }
  771. X
  772. X    /* Adjust checksum to count the "chksum" field as blanks. */
  773. X    for (i = 0; i < 8; i++) {
  774. X    sum -= 0xFF & hdrbuf[148 + i];
  775. X    }
  776. X    sum += ' ' * 8;
  777. X
  778. X    if (sum == 8 * ' ') {
  779. X
  780. X    /*
  781. X     * This is a zeroed record...whole record is 0's except for the 8
  782. X     * blanks we faked for the checksum field. 
  783. X     */
  784. X    return (2);
  785. X    }
  786. X    if (sum == recsum) {
  787. X    /*
  788. X     * Good record.  Decode file size and return. 
  789. X     */
  790. X    if (hdrbuf[156] != LNKTYPE) {
  791. X        asb->sb_size = from_oct(1 + 12, &hdrbuf[124]);
  792. X    }
  793. X    asb->sb_mtime = from_oct(1 + 12, &hdrbuf[136]);
  794. X    asb->sb_mode = from_oct(8, &hdrbuf[100]);
  795. X
  796. X    if (strcmp(&hdrbuf[257], TMAGIC) == 0) {
  797. X        /* Unix Standard tar archive */
  798. X        head_standard = 1;
  799. X#ifdef NONAMES
  800. X        asb->sb_uid = from_oct(8, &hdrbuf[108]);
  801. X        asb->sb_gid = from_oct(8, &hdrbuf[116]);
  802. X#else
  803. X        asb->sb_uid = finduid(&hdrbuf[265]);
  804. X        asb->sb_gid = findgid(&hdrbuf[297]);
  805. X#endif
  806. X        switch (hdrbuf[156]) {
  807. X        case BLKTYPE:
  808. X        case CHRTYPE:
  809. X        asb->sb_rdev = makedev(from_oct(8, &hdrbuf[329]),
  810. X                      from_oct(8, &hdrbuf[337]));
  811. X        break;
  812. X        default:
  813. X        /* do nothing... */
  814. X        break;
  815. X        }
  816. X    } else {
  817. X        /* Old fashioned tar archive */
  818. X        head_standard = 0;
  819. X        asb->sb_uid = from_oct(8, &hdrbuf[108]);
  820. X        asb->sb_gid = from_oct(8, &hdrbuf[116]);
  821. X    }
  822. X
  823. X    switch (hdrbuf[156]) {
  824. X    case REGTYPE:
  825. X    case AREGTYPE:
  826. X        /*
  827. X         * Berkeley tar stores directories as regular files with a
  828. X         * trailing /
  829. X         */
  830. X        if (name[strlen(name) - 1] == '/') {
  831. X        name[strlen(name) - 1] = '\0';
  832. X        asb->sb_mode |= S_IFDIR;
  833. X        } else {
  834. X        asb->sb_mode |= S_IFREG;
  835. X        }
  836. X        break;
  837. X    case LNKTYPE:
  838. X        asb->sb_nlink = 2;
  839. X        linkto(&hdrbuf[157], asb);
  840. X        linkto(name, asb);
  841. X        asb->sb_mode |= S_IFREG;
  842. X        break;
  843. X    case BLKTYPE:
  844. X        asb->sb_mode |= S_IFBLK;
  845. X        break;
  846. X    case CHRTYPE:
  847. X        asb->sb_mode |= S_IFCHR;
  848. X        break;
  849. X    case DIRTYPE:
  850. X        asb->sb_mode |= S_IFDIR;
  851. X        break;
  852. X#ifdef S_IFLNK
  853. X    case SYMTYPE:
  854. X        asb->sb_mode |= S_IFLNK;
  855. X        strcpy(asb->sb_link, &hdrbuf[157]);
  856. X        break;
  857. X#endif
  858. X#ifdef S_IFIFO
  859. X    case FIFOTYPE:
  860. X        asb->sb_mode |= S_IFIFO;
  861. X        break;
  862. X#endif
  863. X#ifdef S_IFCTG
  864. X    case CONTTYPE:
  865. X        asb->sb_mode |= S_IFCTG;
  866. X        break;
  867. X#endif
  868. X    }
  869. X    return (1);
  870. X    }
  871. X    return (0);
  872. X}
  873. X
  874. X
  875. X/* print_entry - print a single table-of-contents entry
  876. X *
  877. X * DESCRIPTION
  878. X * 
  879. X *    Print_entry prints a single line of file information.  The format
  880. X *    of the line is the same as that used by the LS command.  For some
  881. X *    archive formats, various fields may not make any sense, such as
  882. X *    the link count on tar archives.  No error checking is done for bad
  883. X *    or invalid data.
  884. X *
  885. X * PARAMETERS
  886. X *
  887. X *    char   *name        - pointer to name to print an entry for
  888. X *    Stat   *asb        - pointer to the stat structure for the file
  889. X */
  890. X
  891. X#ifdef __STDC__
  892. X
  893. Xvoid print_entry(char *name, Stat *asb)
  894. X
  895. X#else
  896. X    
  897. Xvoid print_entry(name, asb)
  898. Xchar        *name;
  899. XStat            *asb;
  900. X
  901. X#endif
  902. X{
  903. X    switch (ar_interface) {
  904. X    case TAR:
  905. X    tar_entry(name, asb);
  906. X    break;
  907. X    case CPIO:
  908. X    cpio_entry(name, asb);
  909. X    break;
  910. X    case PAX: pax_entry(name, asb);
  911. X    break;
  912. X    }
  913. X}
  914. X
  915. X
  916. X/* cpio_entry - print a verbose cpio-style entry
  917. X *
  918. X * DESCRIPTION
  919. X *
  920. X *    Print_entry prints a single line of file information.  The format
  921. X *    of the line is the same as that used by the traditional cpio 
  922. X *    command.  No error checking is done for bad or invalid data.
  923. X *
  924. X * PARAMETERS
  925. X *
  926. X *    char   *name        - pointer to name to print an entry for
  927. X *    Stat   *asb        - pointer to the stat structure for the file
  928. X */
  929. X
  930. X#ifdef __STDC__
  931. X
  932. Xstatic void cpio_entry(char *name, Stat *asb)
  933. X
  934. X#else
  935. X    
  936. Xstatic void cpio_entry(name, asb)
  937. Xchar           *name;
  938. XStat           *asb;
  939. X
  940. X#endif
  941. X{
  942. X    struct tm           *atm;
  943. X    Link           *from;
  944. X    struct passwd      *pwp;
  945. X    struct group       *grp;
  946. X
  947. X    if (f_list && f_verbose) {
  948. X    fprintf(msgfile, "%-7o", asb->sb_mode);
  949. X    atm = localtime(&asb->sb_mtime);
  950. X    if (pwp = getpwuid((int) USH(asb->sb_uid))) {
  951. X        fprintf(msgfile, "%-6s", pwp->pw_name);
  952. X    } else {
  953. X        fprintf(msgfile, "%-6u", USH(asb->sb_uid));
  954. X    }
  955. X    fprintf(msgfile,"%7ld  %3s %2d %02d:%02d:%02d %4d  ",
  956. X                   asb->sb_size, monnames[atm->tm_mon], 
  957. X               atm->tm_mday, atm->tm_hour, atm->tm_min, 
  958. X               atm->tm_sec, atm->tm_year + 1900);
  959. X    }
  960. X    fprintf(msgfile, "%s", name);
  961. X    if ((asb->sb_nlink > 1) && (from = islink(name, asb))) {
  962. X    fprintf(msgfile, " linked to %s", from->l_name);
  963. X    }
  964. X#ifdef    S_IFLNK
  965. X    if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  966. X    fprintf(msgfile, " symbolic link to %s", asb->sb_link);
  967. X    }
  968. X#endif    /* S_IFLNK */
  969. X    putc('\n', msgfile);
  970. X}
  971. X
  972. X
  973. X/* tar_entry - print a tar verbose mode entry
  974. X *
  975. X * DESCRIPTION
  976. X *
  977. X *    Print_entry prints a single line of tar file information.  The format
  978. X *    of the line is the same as that produced by the traditional tar 
  979. X *    command.  No error checking is done for bad or invalid data.
  980. X *
  981. X * PARAMETERS
  982. X *
  983. X *    char   *name        - pointer to name to print an entry for
  984. X *    Stat   *asb        - pointer to the stat structure for the file
  985. X */
  986. X
  987. X#ifdef __STDC__
  988. X
  989. Xstatic void tar_entry(char *name, Stat *asb)
  990. X
  991. X#else
  992. X    
  993. Xstatic void tar_entry(name, asb)
  994. Xchar        *name;
  995. XStat            *asb;
  996. X
  997. X#endif
  998. X{
  999. X    struct tm             *atm;
  1000. X    int            i;
  1001. X    int            mode;
  1002. X    char               *symnam = "NULL";
  1003. X    Link               *link;
  1004. X
  1005. X    if ((mode = asb->sb_mode & S_IFMT) == S_IFDIR) {
  1006. X    return;            /* don't print directories */
  1007. X    }
  1008. X    if (f_extract) {
  1009. X    switch (mode) {
  1010. X#ifdef S_IFLNK
  1011. X    case S_IFLNK:     /* This file is a symbolic link */
  1012. X        i = readlink(name, symnam, PATH_MAX - 1);
  1013. X        if (i < 0) {        /* Could not find symbolic link */
  1014. X        warn("can't read symbolic link", syserr());
  1015. X        } else {         /* Found symbolic link filename */
  1016. X        symnam[i] = '\0';
  1017. X        fprintf(msgfile, "x %s symbolic link to %s\n", name, symnam);
  1018. X        }
  1019. X        break;
  1020. X#endif
  1021. X    case S_IFREG:     /* It is a link or a file */
  1022. X        if ((asb->sb_nlink > 1) && (link = islink(name, asb))) {
  1023. X        fprintf(msgfile, "%s linked to %s\n", name, link->l_name); 
  1024. X        } else {
  1025. X        fprintf(msgfile, "x %s, %d bytes, %d tape blocks\n", 
  1026. X            name, asb->sb_size, ROUNDUP(asb->sb_size, 
  1027. X            BLOCKSIZE) / BLOCKSIZE);
  1028. X        }
  1029. X    }
  1030. X    } else if (f_append || f_create) {
  1031. X    switch (mode) {
  1032. X#ifdef S_IFLNK
  1033. X    case S_IFLNK:     /* This file is a symbolic link */
  1034. X        i = readlink(name, symnam, PATH_MAX - 1);
  1035. X        if (i < 0) {        /* Could not find symbolic link */
  1036. X        warn("can't read symbolic link", syserr());
  1037. X        } else {         /* Found symbolic link filename */
  1038. X        symnam[i] = '\0';
  1039. X        fprintf(msgfile, "a %s symbolic link to %s\n", name, symnam);
  1040. X        }
  1041. X        break;
  1042. X#endif
  1043. X    case S_IFREG:     /* It is a link or a file */
  1044. X        fprintf(msgfile, "a %s ", name);
  1045. X        if ((asb->sb_nlink > 1) && (link = islink(name, asb))) {
  1046. X        fprintf(msgfile, "link to %s\n", link->l_name); 
  1047. X        } else {
  1048. X        fprintf(msgfile, "%d Blocks\n", 
  1049. X            ROUNDUP(asb->sb_size, BLOCKSIZE) / BLOCKSIZE);
  1050. X        }
  1051. X        break;
  1052. X    }
  1053. X    } else if (f_list) {
  1054. X    if (f_verbose) {
  1055. X        atm = localtime(&asb->sb_mtime);
  1056. X        print_mode(asb->sb_mode);
  1057. X        fprintf(msgfile," %d/%d %6d %3s %2d %02d:%02d %4d %s",
  1058. X            asb->sb_uid, asb->sb_gid, asb->sb_size,
  1059. X            monnames[atm->tm_mon], atm->tm_mday, atm->tm_hour, 
  1060. X            atm->tm_min, atm->tm_year + 1900, name);
  1061. X    } else {
  1062. X        fprintf(msgfile, "%s", name);
  1063. X    }
  1064. X    switch (mode) {
  1065. X#ifdef S_IFLNK
  1066. X    case S_IFLNK:     /* This file is a symbolic link */
  1067. X        i = readlink(name, symnam, PATH_MAX - 1);
  1068. X        if (i < 0) {        /* Could not find symbolic link */
  1069. X        warn("can't read symbolic link", syserr());
  1070. X        } else {         /* Found symbolic link filename */
  1071. X        symnam[i] = '\0';
  1072. X        fprintf(msgfile, " symbolic link to %s", name, symnam);
  1073. X        }
  1074. X        break;
  1075. X#endif
  1076. X    case S_IFREG:     /* It is a link or a file */
  1077. X        if ((asb->sb_nlink > 1) && (link = islink(name, asb))) {
  1078. X        fprintf(msgfile, " linked to %s", link->l_name);
  1079. X        }
  1080. X        break;        /* Do not print out directories */
  1081. X    }
  1082. X    fputc('\n', msgfile);
  1083. X    } else {
  1084. X    fprintf(msgfile, "? %s %d blocks\n", name,
  1085. X        ROUNDUP(asb->sb_size, BLOCKSIZE) / BLOCKSIZE);
  1086. X    }
  1087. X}
  1088. X
  1089. X
  1090. X/* pax_entry - print a verbose cpio-style entry
  1091. X *
  1092. X * DESCRIPTION
  1093. X *
  1094. X *    Print_entry prints a single line of file information.  The format
  1095. X *    of the line is the same as that used by the LS command.  
  1096. X *    No error checking is done for bad or invalid data.
  1097. X *
  1098. X * PARAMETERS
  1099. X *
  1100. X *    char   *name        - pointer to name to print an entry for
  1101. X *    Stat   *asb        - pointer to the stat structure for the file
  1102. X */
  1103. X
  1104. X#ifdef __STDC__
  1105. X
  1106. Xstatic void pax_entry(char *name, Stat *asb)
  1107. X
  1108. X#else
  1109. X    
  1110. Xstatic void pax_entry(name, asb)
  1111. Xchar           *name;
  1112. XStat           *asb;
  1113. X
  1114. X#endif
  1115. X{
  1116. X    struct tm           *atm;
  1117. X    Link           *from;
  1118. X    struct passwd      *pwp;
  1119. X    struct group       *grp;
  1120. X
  1121. X    if (f_list && f_verbose) {
  1122. X    print_mode(asb->sb_mode);
  1123. X    fprintf(msgfile, " %2d", asb->sb_nlink);
  1124. X    atm = localtime(&asb->sb_mtime);
  1125. X    if (pwp = getpwuid((int) USH(asb->sb_uid))) {
  1126. X        fprintf(msgfile, " %-8s", pwp->pw_name);
  1127. X    } else {
  1128. X        fprintf(msgfile, " %-8u", USH(asb->sb_uid));
  1129. X    }
  1130. X    if (grp = getgrgid((int) USH(asb->sb_gid))) {
  1131. X        fprintf(msgfile, " %-8s", grp->gr_name);
  1132. X    } else {
  1133. X        fprintf(msgfile, " %-8u", USH(asb->sb_gid));
  1134. X    }
  1135. X    switch (asb->sb_mode & S_IFMT) {
  1136. X    case S_IFBLK:
  1137. X    case S_IFCHR:
  1138. X        fprintf(msgfile, "\t%3d, %3d",
  1139. X                   major(asb->sb_rdev), minor(asb->sb_rdev));
  1140. X        break;
  1141. X    case S_IFREG:
  1142. X        fprintf(msgfile, "\t%8ld", asb->sb_size);
  1143. X        break;
  1144. X    default:
  1145. X        fprintf(msgfile, "\t        ");
  1146. X    }
  1147. X    fprintf(msgfile," %3s %2d %02d:%02d ",
  1148. X                   monnames[atm->tm_mon], atm->tm_mday, 
  1149. X               atm->tm_hour, atm->tm_min);
  1150. X    }
  1151. X    fprintf(msgfile, "%s", name);
  1152. X    if ((asb->sb_nlink > 1) && (from = islink(name, asb))) {
  1153. X    fprintf(msgfile, " == %s", from->l_name);
  1154. X    }
  1155. X#ifdef    S_IFLNK
  1156. X    if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  1157. X    fprintf(msgfile, " -> %s", asb->sb_link);
  1158. X    }
  1159. X#endif    /* S_IFLNK */
  1160. X    putc('\n', msgfile);
  1161. X}
  1162. X
  1163. X
  1164. X
  1165. X
  1166. X/* print_mode - fancy file mode display
  1167. X *
  1168. X * DESCRIPTION
  1169. X *
  1170. X *    Print_mode displays a numeric file mode in the standard unix
  1171. X *    representation, ala ls (-rwxrwxrwx).  No error checking is done
  1172. X *    for bad mode combinations.  FIFOS, sybmbolic links, sticky bits,
  1173. X *    block- and character-special devices are supported if supported
  1174. X *    by the hosting implementation.
  1175. X *
  1176. X * PARAMETERS
  1177. X *
  1178. X *    ushort    mode    - The integer representation of the mode to print.
  1179. X */
  1180. X
  1181. X#ifdef __STDC__
  1182. X
  1183. Xstatic void print_mode(ushort mode)
  1184. X
  1185. X#else
  1186. X    
  1187. Xstatic void print_mode(mode)
  1188. Xushort    mode;
  1189. X
  1190. X#endif
  1191. X{
  1192. X    /* Tar does not print the leading identifier... */
  1193. X    if (ar_interface != TAR) {
  1194. X    switch (mode & S_IFMT) {
  1195. X    case S_IFDIR: 
  1196. X        putc('d', msgfile); 
  1197. X        break;
  1198. X#ifdef    S_IFLNK
  1199. X    case S_IFLNK: 
  1200. X        putc('l', msgfile); 
  1201. X        break;
  1202. X#endif    /* S_IFLNK */
  1203. X    case S_IFBLK: 
  1204. X        putc('b', msgfile); 
  1205. X        break;
  1206. X    case S_IFCHR: 
  1207. X        putc('c', msgfile); 
  1208. X        break;
  1209. X#ifdef    S_IFIFO
  1210. X    case S_IFIFO: 
  1211. X        putc('p', msgfile); 
  1212. X        break; 
  1213. X#endif    /* S_IFIFO */ 
  1214. X    case S_IFREG: 
  1215. X    default:
  1216. X        putc('-', msgfile); 
  1217. X        break;
  1218. X    }
  1219. X    }
  1220. X    putc(mode & 0400 ? 'r' : '-', msgfile);
  1221. X    putc(mode & 0200 ? 'w' : '-', msgfile);
  1222. X    putc(mode & 0100
  1223. X     ? mode & 04000 ? 's' : 'x'
  1224. X     : mode & 04000 ? 'S' : '-', msgfile);
  1225. X    putc(mode & 0040 ? 'r' : '-', msgfile);
  1226. X    putc(mode & 0020 ? 'w' : '-', msgfile);
  1227. X    putc(mode & 0010
  1228. X     ? mode & 02000 ? 's' : 'x'
  1229. X     : mode & 02000 ? 'S' : '-', msgfile);
  1230. X    putc(mode & 0004 ? 'r' : '-', msgfile);
  1231. X    putc(mode & 0002 ? 'w' : '-', msgfile);
  1232. X    putc(mode & 0001
  1233. X     ? mode & 01000 ? 't' : 'x'
  1234. X     : mode & 01000 ? 'T' : '-', msgfile);
  1235. X}
  1236. X
  1237. X
  1238. X/* from_oct - quick and dirty octal conversion
  1239. X *
  1240. X * DESCRIPTION
  1241. X *
  1242. X *    From_oct will convert an ASCII representation of an octal number
  1243. X *    to the numeric representation.  The number of characters to convert
  1244. X *    is given by the parameter "digs".  If there are less numbers than
  1245. X *    specified by "digs", then the routine returns -1.
  1246. X *
  1247. X * PARAMETERS
  1248. X *
  1249. X *    int digs    - Number to of digits to convert 
  1250. X *    char *where    - Character representation of octal number
  1251. X *
  1252. X * RETURNS
  1253. X *
  1254. X *    The value of the octal number represented by the first digs
  1255. X *    characters of the string where.  Result is -1 if the field 
  1256. X *    is invalid (all blank, or nonoctal). 
  1257. X *
  1258. X * ERRORS
  1259. X *
  1260. X *    If the field is all blank, then the value returned is -1.
  1261. X *
  1262. X */
  1263. X
  1264. X#ifdef __STDC__
  1265. X
  1266. Xstatic long from_oct(int digs, char *where)
  1267. X
  1268. X#else
  1269. X
  1270. Xstatic long from_oct(digs, where)
  1271. Xint             digs;        /* number of characters to convert */
  1272. Xchar           *where;        /* character representation of octal number */
  1273. X
  1274. X#endif
  1275. X{
  1276. X    long            value;
  1277. X
  1278. X    while (isspace(*where)) {    /* Skip spaces */
  1279. X    where++;
  1280. X    if (--digs <= 0) {
  1281. X        return(-1);        /* All blank field */
  1282. X    }
  1283. X    }
  1284. X    value = 0;
  1285. X    while (digs > 0 && ISODIGIT(*where)) {    /* Scan til nonoctal */
  1286. X    value = (value << 3) | (*where++ - '0');
  1287. X    --digs;
  1288. X    }
  1289. X
  1290. X    if (digs > 0 && *where && !isspace(*where)) {
  1291. X    return(-1);        /* Ended on non-space/nul */
  1292. X    }
  1293. X    return(value);
  1294. X}
  1295. END_OF_list.c
  1296. if test 16229 -ne `wc -c <list.c`; then
  1297.     echo shar: \"list.c\" unpacked with wrong size!
  1298. fi
  1299. # end of overwriting check
  1300. fi
  1301. if test -f pax.1 -a "${1}" != "-c" ; then 
  1302.   echo shar: Will not over-write existing file \"pax.1\"
  1303. else
  1304. echo shar: Extracting \"pax.1\" \(13279 characters\)
  1305. sed "s/^X//" >pax.1 <<'END_OF_pax.1'
  1306. X.\" $Id: pax.1,v 1.1 88/12/23 18:02:22 mark Rel $
  1307. X.TH PAX 1 "USENIX Association" ""
  1308. X.SH NAME
  1309. Xpax \- portable archive exchange 
  1310. X.SH SYNOPSIS
  1311. X.TP \w'\fBpax\fR\ 'u
  1312. X.B pax
  1313. X.RB [ \-cimopuvy ]
  1314. X.RI "[\fB\-f\fR" " archive" ]
  1315. X.RI "[\fB\-s\fR" " replstr" ]
  1316. X.RI "[\fB\-t\fR" " device" ] 
  1317. X.RI [ pattern... ]
  1318. X.TP \w'\fBpax\ \-r\fR\ 'u
  1319. X.B "pax\ \-r"
  1320. X.RB [ \-cimnopuvy ]
  1321. X.RI "[\fB\-f\fR" " archive" ]
  1322. X.RI "[\fB\-s\fR" " replstr" ] 
  1323. X.RI "[\fB\-t\fR" " device" ] 
  1324. X.RI [ pattern... ]
  1325. X.TP \w'\fBpax\ \-w\fR\ 'u
  1326. X.B "pax\ \-w"
  1327. X.RB [ \-adimuvy ] 
  1328. X.RI "[\fB\-b\fR" " blocking" ]
  1329. X.RI "[\fB\-f\fR" " archive" ] 
  1330. X.RI "[\fB\-s\fR" " replstr" ] 
  1331. X.RI "[\fB\-t\fR" " device" ] 
  1332. X.RI "[\fB\-x\fR" " format" ]
  1333. X.RI [ pathname... ]
  1334. X.TP \w'\fBpax\ \-rw\fR\ 'u
  1335. X.B "pax\ \-rw"
  1336. X.RB [ \-ilmopuvy ] 
  1337. X.RI "[\fB\-s\fR" " replstr" ] 
  1338. X.RI [ pathname... ]
  1339. Xdirectory
  1340. X.SH DESCRIPTION
  1341. X.I Pax 
  1342. Xreads and writes archive files which conform to the 
  1343. X.B "Archive/Interchange File Format" 
  1344. Xspecified in 
  1345. X.IR "IEEE Std. 1003.1-1988" .
  1346. X.I Pax
  1347. Xcan also read, but not write, a number of other file formats
  1348. Xin addition to those specified in the 
  1349. X.B "Archive/Interchange File Format"
  1350. Xdescription.
  1351. XSupport for these traditional file formats, such as V7 
  1352. X.I "tar" 
  1353. Xand System V binary 
  1354. X.I "cpio" 
  1355. Xformat archives,
  1356. Xis provided for backward compatibility and to maximize portability.
  1357. X.PP
  1358. X.I Pax 
  1359. Xwill also support traditional 
  1360. X.I cpio 
  1361. Xand 
  1362. XSystem V
  1363. X.I tar
  1364. Xinterfaces if invoked with the name
  1365. X"cpio" or "tar" respectively.
  1366. XSee the 
  1367. X.I cpio(1) 
  1368. Xor 
  1369. X.I tar(1)
  1370. Xmanual pages for more details.
  1371. X.PP
  1372. XCombinations of the
  1373. X.B \-r 
  1374. Xand 
  1375. X.B \-w
  1376. Xcommand line arguments specify whether 
  1377. X.I pax 
  1378. Xwill read, write or list the contents of the specified archive,
  1379. Xor move the specified files to another directory.
  1380. X.PP
  1381. XThe command line arguments are:
  1382. X.TP .5i
  1383. X.B \-w
  1384. Xwrites the files and directories specified by 
  1385. X.I pathname
  1386. Xoperands to the standard output together with the pathname and status 
  1387. Xinformation prescribed by the archive format used.
  1388. XA directory
  1389. X.I pathname
  1390. Xoperand refers to the files and (recursively) subdirectories of that 
  1391. Xdirectory.
  1392. XIf no 
  1393. X.I pathname 
  1394. Xoperands are given, then the standard input is read to get a
  1395. Xlist of pathnames to copy, one pathname per line.
  1396. XIn this case, only those pathnames appearing on the standard input are
  1397. Xcopied.
  1398. X.TP .5i
  1399. X.B \-r
  1400. X.I Pax
  1401. Xreads an archive file from the standard input.
  1402. XOnly files with names that match any of the 
  1403. X.I pattern
  1404. Xoperands are selected for extraction.
  1405. XThe selected files are conditionally created and copied relative to the
  1406. Xcurrent directory tree, subject to the options described below.
  1407. XBy default, the owner and group of selected files will be that of the
  1408. Xinvoking process, and the permissions and modification times will be the
  1409. Xsames as those in the archive.
  1410. X.RS .5i
  1411. X.PP
  1412. XThe supported archive formats are automatically detected on input.
  1413. XThe default output format is 
  1414. X.IR ustar ,
  1415. Xbut may be overridden by the 
  1416. X.B \-x
  1417. X.I format
  1418. Xoption described below.
  1419. X.RE
  1420. X.TP .5i
  1421. X.B \-rw
  1422. X.I Pax 
  1423. Xreads the files and directories named in the
  1424. X.I pathname
  1425. Xoperands and copies them to the destination 
  1426. X.IR directory .
  1427. XA directory
  1428. X.I pathname 
  1429. Xoperand refers to the files and (recursively) subdirectories of that
  1430. Xdirectory.
  1431. XIf no 
  1432. X.I pathname
  1433. Xoperands are given, the standard input is read to get a list of pathnames
  1434. Xto copy, one pathname per line.
  1435. XIn this case, only those pathnames appearing on the standard input are
  1436. Xcopied.
  1437. XThe directory named by the 
  1438. X.I directory
  1439. Xoperand must exist and have the proper permissions before the copy can
  1440. Xoccur.
  1441. X.PP
  1442. XIf neither the
  1443. X.BR \-r " or " \-w 
  1444. Xoptions are given, then 
  1445. X.I pax
  1446. Xwill list the contents of the specified archive.
  1447. XIn this mode, 
  1448. X.I pax 
  1449. Xlists normal files one per line, hard link pathnames as
  1450. X.sp
  1451. X.RS 1i
  1452. X.IR pathname " == " linkname
  1453. X.RE
  1454. X.sp
  1455. Xand symbolic link pathnames (if supported by the implementation) as
  1456. X.sp
  1457. X.RS 1i
  1458. X.IR pathname " -> " linkname
  1459. X.RE
  1460. X.sp
  1461. Xwhere 
  1462. X.I pathname
  1463. Xis the name of the file being extracted, and
  1464. X.I linkname
  1465. Xis the name of a file which appeared earlier in the archive.
  1466. X.PP
  1467. XIf the 
  1468. X.B \-v
  1469. Xoption is specified, then 
  1470. X.I pax 
  1471. Xlist normal pathnames in the same format used by the 
  1472. X.I ls
  1473. Xutility with the
  1474. X.B \-l
  1475. Xoption.
  1476. XHard links are shown as
  1477. X.sp
  1478. X.RS 1i
  1479. X.IR "<ls -l listing>" " == " linkname
  1480. X.RE
  1481. X.sp
  1482. Xand symbolic links (if supported) are shown as
  1483. X.sp
  1484. X.RS 1i
  1485. X.IR "<ls -l listing>" " -> " linkname
  1486. X.RE
  1487. X.sp 
  1488. X.PP
  1489. X.I Pax 
  1490. Xis capable of reading and writing archives which span multiple physical 
  1491. Xvolumes.
  1492. XUpon detecting an end of medium on an archive which is not yet completed,
  1493. X.I pax 
  1494. Xwill prompt the user for the next volume of the archive and will allow the 
  1495. Xuser to specify the location of the next volume.
  1496. X.SS Options
  1497. XThe following options are available:
  1498. X.TP 1i
  1499. X.B \-a
  1500. XThe files specified by
  1501. X.I pathname
  1502. Xare appended to the specified archive.
  1503. X.TP 1i
  1504. X.BI \-b " blocking"
  1505. XBlock the output at
  1506. X.I blocking
  1507. Xbytes per write to the archive file.
  1508. XA 
  1509. X.B k
  1510. Xsuffix multiplies 
  1511. X.I blocking 
  1512. Xby 1024, a
  1513. X.B b 
  1514. Xsuffix multiplies 
  1515. X.I blocking 
  1516. Xby 512 and a 
  1517. X.B m
  1518. Xsuffix multiplies 
  1519. X.I blocking 
  1520. Xby 1048576 (1 megabyte).
  1521. XIf not specified,
  1522. X.I blocking 
  1523. Xis automatically determined on input and is ignored for 
  1524. X.B \-rw.
  1525. X.TP 1i
  1526. X.B \-c
  1527. XComplement the match sense of the the 
  1528. X.I pattern
  1529. Xoperands.
  1530. X.TP 1i
  1531. X.B \-d
  1532. XIntermediate directories not explicitly listed in the archive are not 
  1533. Xcreated.
  1534. XThis option is ignored unless
  1535. Xthe 
  1536. X.B \-r
  1537. Xoption is specified.
  1538. X.TP 1i
  1539. X.BI \-f " archive"
  1540. XThe
  1541. X.I archive
  1542. Xoption specifies the pathname of the input or output archive,
  1543. Xoverriding the default of standard input for 
  1544. X.B \-r
  1545. Xor standard output for
  1546. X.BR \-w .
  1547. X.TP 1i
  1548. X.B \-i
  1549. XInteractively rename files.
  1550. XSubstitutions specified by 
  1551. X.B \-s
  1552. Xoptions (described below)
  1553. Xare performed before requesting the new file name from the user.
  1554. XA file is skipped if an empty line is entered and
  1555. X.I pax
  1556. Xexits with an exit status of 0 if 
  1557. X.B EOF 
  1558. Xis encountered.
  1559. X.TP 1i
  1560. X.B \-l
  1561. XFiles are linked rather than copied when possible.
  1562. X.TP 1i
  1563. X.B \-m
  1564. XFile modification times are not retained.
  1565. X.TP 1i
  1566. X.B \-n
  1567. XWhen 
  1568. X.B \-r
  1569. Xis specified, but
  1570. X.B \-w
  1571. Xis not, the 
  1572. X.I pattern
  1573. Xarguments are treated as ordinary file names.
  1574. XOnly the first occurrence of each of these files in the input archive
  1575. Xis read.
  1576. XThe
  1577. X.B pax
  1578. Xutility exits with a zero exit status after all files in the list have been
  1579. Xread.
  1580. XIf one or more files in the list is not found,
  1581. X.B pax
  1582. Xwrites a diagnostic to standard error for each of the files and exits with
  1583. Xa non-zero exit status.
  1584. Xthe file names are compared before any of the 
  1585. X.BR \-i ,
  1586. X.BR \-s ,
  1587. Xor
  1588. X.B \-y
  1589. Xoptions are applied.
  1590. X.TP 1i
  1591. X.B \-o
  1592. XRestore file ownership as specified in the archive.
  1593. XThe invoking process must have appropriate privileges to accomplish this.
  1594. X.TP 1i
  1595. X.B \-p
  1596. XPreserve the access time of the input files after they have been copied.
  1597. X.TP 1i
  1598. X.BI \-s " replstr"
  1599. XFile names are modified according to the substitution expression using the 
  1600. Xsyntax of 
  1601. X.I "ed(1)"
  1602. Xas shown:
  1603. X.sp
  1604. X.RS 2i
  1605. X-s /\fIold\fR/\fInew\fR/\fB[\fRgp\fB]\fR
  1606. X.RE
  1607. X.RS 1i
  1608. X.PP
  1609. XAny non null character may be used as a delimiter (a / is used here as an
  1610. Xexample).
  1611. XMultiple 
  1612. X.B \-s
  1613. Xexpressions may be specified; the expressions are applied in the order
  1614. Xspecified terminating with the first successful substitution.
  1615. XThe optional trailing 
  1616. X.B p
  1617. Xcauses successful mappings to be listed on standard error.
  1618. XThe optional trailing
  1619. X.B g
  1620. Xcauses the 
  1621. X.I old 
  1622. Xexpression to be replaced each time it occurs in the source string.
  1623. XFiles that substitute to an empty string are ignored both on input and
  1624. Xoutput.
  1625. X.RE
  1626. X.TP 1i
  1627. X.BI \-t " device"
  1628. XThe
  1629. X.I device
  1630. Xoption argument is an implementation-defined identifier that names the input
  1631. Xor output archive device, overriding the default of standard input for
  1632. X.B \-r
  1633. Xand standard output for
  1634. X.BR \-w .
  1635. X.TP 1i
  1636. X.B \-u
  1637. XCopy each file only if it is newer than a pre-existing file with the same
  1638. Xname.
  1639. XThis implies 
  1640. X.BR \-a .
  1641. X.TP 1i
  1642. X.B \-v
  1643. XList file names as they are encountered.
  1644. XProduces a verbose table of contents listing on the standard output when both 
  1645. X.B \-r 
  1646. Xand
  1647. X.B \-w
  1648. Xare omitted,
  1649. Xotherwise the file names are printed to standard error as they are
  1650. Xencountered in the archive.
  1651. X.TP 1i
  1652. X.BI \-x " format"
  1653. XSpecifies the output archive
  1654. X.IR format .
  1655. XThe input format, which must be one of the following, is automatically
  1656. Xdetermined when the
  1657. X.B \-r 
  1658. Xoption is used.
  1659. XThe supported formats are:
  1660. X.TP 1i
  1661. X.I cpio
  1662. XThe extended 
  1663. X.I CPIO
  1664. Xinterchange format specified in
  1665. X.B "Extended CPIO Format" in 
  1666. X.I "IEEE Std. 1003.1-1988."
  1667. X.TP 1i
  1668. X.I ustar
  1669. XThe extended 
  1670. X.I TAR
  1671. Xinterchange format specified in
  1672. X.B "Extended TAR Format" in 
  1673. X.I "IEEE Std. 1003.1-1988."
  1674. XThis is the default archive format.
  1675. X.RE
  1676. X.TP 1i
  1677. X.B \-y
  1678. XInteractively prompt for the disposition of each file.
  1679. XSubstitutions specified by 
  1680. X.B \-s
  1681. Xoptions (described above)
  1682. Xare performed before prompting the user for disposition.
  1683. X.B EOF
  1684. Xor an input line starting with the character
  1685. X.B q
  1686. Xcaused
  1687. X.I pax
  1688. Xto exit.
  1689. XOtherwise, an input line starting with anything other than 
  1690. X.B y
  1691. Xcauses the file to be ignored.
  1692. XThis option cannot be used in conjunction with the 
  1693. X.B \-i 
  1694. Xoption.
  1695. X.PP
  1696. XOnly the last of multiple 
  1697. X.B \-f 
  1698. Xor
  1699. X.B \-t
  1700. Xoptions take effect.
  1701. X.PP
  1702. XWhen writing to an archive, the
  1703. Xstandard input is used as a list of pathnames if no
  1704. X.I pathname
  1705. Xoperands are specified.
  1706. XThe format is one pathname per line.
  1707. XOtherwise, the standard input is the archive file,
  1708. Xwhich is formatted according to one of the specifications in
  1709. X.B "Archive/Interchange File format"
  1710. Xin 
  1711. X.IR "IEEE Std. 1003.1-1988" ,
  1712. Xor some other implementation-defined format.
  1713. X.PP
  1714. XThe user ID and group ID of the process, together with the appropriate
  1715. Xprivileges, affect the ability of 
  1716. X.I pax
  1717. Xto restore ownership and permissions attributes of the archived files.
  1718. X(See 
  1719. X.I "format-reading utility"
  1720. Xin
  1721. X.B "Archive/Interchange File Format"
  1722. Xin 
  1723. X.IR "IEEE Std. 1003.1-1988" ".)"
  1724. X.PP
  1725. XThe options
  1726. X.BR \-a ,
  1727. X.BR \-c ,
  1728. X.BR \-d ,
  1729. X.BR \-i ,
  1730. X.BR \-l ,
  1731. X.BR \-p ,
  1732. X.BR \-t ,
  1733. X.BR \-u ,
  1734. Xand
  1735. X.BR \-y 
  1736. Xare provided for functional compatibility with the historical
  1737. X.I cpio
  1738. Xand
  1739. X.I tar
  1740. Xutilities.
  1741. XThe option defaults were chosen based on the most common usage of these
  1742. Xoptions, therefore, some of the options have meanings different than
  1743. Xthose of the historical commands.
  1744. X.SS Operands
  1745. XThe following operands are available:
  1746. X.TP 1i
  1747. X.I directory
  1748. XThe destination directory pathname for copies when both the
  1749. X.B \-r
  1750. Xand 
  1751. X.B \-w
  1752. Xoptions are specified.
  1753. XThe directory must exist and be writable before the copy or and error
  1754. Xresults.
  1755. X.TP 1i
  1756. X.I pathname
  1757. XA file whose contents are used instead of the files named on the standard
  1758. Xinput.
  1759. XWhen a directory is named, all of its files and (recursively) 
  1760. Xsubdirectories
  1761. Xare copied as well.
  1762. X.TP 1i
  1763. X.IR pattern 
  1764. XA
  1765. X.I pattern
  1766. Xis given in the standard shell pattern matching notation.
  1767. XThe default if no 
  1768. X.I pattern 
  1769. Xis  specified is
  1770. X.BR * \,
  1771. Xwhich selects all files.
  1772. X.SH EXAMPLES
  1773. XThe following command
  1774. X.sp
  1775. X.RS 1i
  1776. Xpax \-w \-f /dev/rmt0 \.
  1777. X.RE
  1778. X.sp
  1779. Xcopies the contents of the current directory to tape drive 0.
  1780. X.PP
  1781. XThe commands
  1782. X.sp
  1783. X.RS 1i
  1784. X.RI mkdir " newdir"
  1785. X.br
  1786. X.RI cd " olddir"
  1787. X.br
  1788. X.RI "pax -rw . " newdir
  1789. X.RE
  1790. X.sp
  1791. Xcopies the contents of 
  1792. X.I olddir 
  1793. Xto 
  1794. X.I newdir .
  1795. X.PP
  1796. XThe command
  1797. X.sp
  1798. X.RS 1i
  1799. Xpax \-r \-s ',//*usr//*,,' -f pax.out
  1800. X.RE
  1801. X.sp
  1802. Xreads the archive 
  1803. X.B pax.out
  1804. Xwith all files rooted in "/usr" in the archive extracted
  1805. Xrelative to the current directory.
  1806. X.SH FILES
  1807. X.TP 1i
  1808. X/dev/tty
  1809. Xused to prompt the user for information when the
  1810. X.BR \-i " or " \-y
  1811. Xoptions are specified. 
  1812. X.SH "SEE ALSO"
  1813. Xcpio(1), find(1), tar(1), cpio(5), tar(5)
  1814. X.SH DIAGNOSTICS
  1815. X.I Pax
  1816. Xwill terminate immediately, without processing any 
  1817. Xadditional files on the command line or in the archive.
  1818. X.SH "EXIT CODES"
  1819. X.I Pax 
  1820. Xwill exit with one of the following values:
  1821. X.IP 0 .5i
  1822. XAll files in the archive were processed successfully.
  1823. X.IP ">0" .5i
  1824. X.I Pax 
  1825. Xaborted due to errors encountered during operation.
  1826. X.SH BUGS
  1827. XSpecial permissions may be required to copy or extract special files.
  1828. X.PP
  1829. XDevice, user ID, and group ID numbers larger than 65535 cause additional
  1830. Xheader records to be output.
  1831. XThese records are ignored by some historical version of
  1832. X.I "cpio(1)"
  1833. Xand
  1834. X.IR "tar(1)" .
  1835. X.PP
  1836. XThe archive formats described in
  1837. X.B "Archive/Interchange File Format" 
  1838. Xhave certain restrictions that have
  1839. Xbeen carried over from historical usage.
  1840. XFor example, there are restrictions on the length of pathnames stored in
  1841. Xthe archive.
  1842. X.PP
  1843. XWhen getting an "ls -l" style listing on
  1844. X.I tar
  1845. Xformat archives, link counts are listed as zero since the 
  1846. X.I ustar
  1847. Xarchive format does not keep link count information.
  1848. X.SH COPYRIGHT
  1849. XCopyright (c) 1989 Mark H. Colburn.  
  1850. X.br
  1851. XAll rights reserved.
  1852. X.PP
  1853. XRedistribution and use in source and binary forms are permitted
  1854. Xprovided that the above copyright notice is duplicated in all such 
  1855. Xforms and that any documentation, advertising materials, and other 
  1856. Xmaterials related to such distribution and use acknowledge that the 
  1857. Xsoftware was developed by Mark H. Colburn and sponsored by The 
  1858. XUSENIX Association. 
  1859. X.PP
  1860. XTHE SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1861. XIMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1862. XWARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1863. X.SH AUTHOR
  1864. XMark H. Colburn
  1865. X.br
  1866. XNAPS International
  1867. X.br
  1868. X117 Mackubin Street, Suite 1
  1869. X.br
  1870. XSt. Paul, MN 55102
  1871. X.br
  1872. Xmark@jhereg.MN.ORG
  1873. X.sp 2
  1874. XSponsored by
  1875. X.B "The USENIX Association"
  1876. Xfor public distribution.
  1877. END_OF_pax.1
  1878. if test 13279 -ne `wc -c <pax.1`; then
  1879.     echo shar: \"pax.1\" unpacked with wrong size!
  1880. fi
  1881. # end of overwriting check
  1882. fi
  1883. echo shar: End of archive 4 \(of 6\).
  1884. cp /dev/null ark4isdone
  1885. MISSING=""
  1886. for I in 1 2 3 4 5 6 ; do
  1887.     if test ! -f ark${I}isdone ; then
  1888.     MISSING="${MISSING} ${I}"
  1889.     fi
  1890. done
  1891. if test "${MISSING}" = "" ; then
  1892.     echo You have unpacked all 6 archives.
  1893.     rm -f ark[1-9]isdone
  1894. else
  1895.     echo You still need to unpack the following archives:
  1896.     echo "        " ${MISSING}
  1897. fi
  1898. ##  End of shell archive.
  1899. exit 0
  1900.  
  1901.